<?php
class User extends AppModel {
	
	var $actsAs=array('Ban');

	var $validate = array(
		'login' => array(
			'notempty' => array(
				'rule' => array('between', 4, 20),
				'message' => 'Tu nombre de usuario debe tener entre 4 y 20 caracteres',
			),'unique' =>array(
				'rule' => array('isUnique'),
				'message' => 'El nombre de usuario ya existe, elige otro',
			)
		),'password' => array(
			'lenght' => array(
				'rule' => array('minLength',6),
        		'message'=>'Tu contraseña debe tener al menos 6 caracteres'
        	)
        ),'email' => array(
			'email' => array(
				'rule' => array('email',true),
				'message' => 'El mail no es valido',
				'allowEmpty' => false,
        		//'on' => 'create', // Limit validation to 'create' or 'update' operations
        	),'unique' =>array(
				'rule' => array('isUnique'),
				'message' => 'El mail ya pertenece a un usuario, si es tuyo haz click en recordar contraseña',
        	)
        )
	);

	// The Associations below have been created with all possible keys, those that are not needed can be removed

    var $hasMany = array(
		'Comment','Favorite','Link','Log','Post','Sneaker','Trackback' ,'Vote'
	);
	
	/**
	 * 
	 * if a check fails throws a addlinkexception with the error message ...
	 */
	function checkCanPostLinks(){
		$checks=array(
			'basicCheck'=>array(),
			'normal'=>array('checkMinKarmaForAddLink','checkIpNotBanned','checkLinkAddByClons','checkLinksSentByUser','checkLinksSentByUserInLast3Minutes','checkUserHaveEnoughVotes','checkRubbishAndSpamSending'),
			'colaborator'=>array('checkUserHaveEnoughVotes','checkRubbishAndSpamSending'),
			'moderator'=>array('checkUserHaveEnoughVotes','checkRubbishAndSpamSending'),
			'admin'=>array(),
			'god'=>array()
		);
		
		try{
			foreach (am($checks['basicCheck'],$checks[$this->field('level')]) as $check){
				$this->$check();
			}
		}catch (UserErrorException $exception){
			throw new AddLinkException($exception->getMessage());
		}
	}

	function checkMinKarmaForAddLink(){
		$min_karma_for_links=Configure::read('Monky.Links.min_karma_for_add');
		if ($min_karma_for_links > 0 && $this->field('karma') < $min_karma_for_links ) {
			throw new AddLinkException(__('you dont have the minimum karme for send links',true));
		}
	}
	
	function checkIpNotBanned(){
		if($this->notBannedIp(Visitor::ip())) return;
		
		throw new UserErrorException(__('your IP is banned',true));
	}
		
	function checkLinkAddByClons(){
		// Don't allow to send a link by a clone 
		$hours = intval(Configure::read('Monky.Links.user_clon_interval'));
		$clones = ClassRegistry::init('Clon')->getClones($this->id,$hours+1);
		if ($hours > 0 && !empty($clones)) {
			$c = (int)$this->Link->find('count',array('conditions'=>array('Link.status'=>'published','Link.created >'=>'date_sub(now(), interval '.$hours.' hour)', 'Link.user_id'=>$clones),'recursive'=>-1));
			if ($c > 0) {
				throw new AddLinkException(__('ya se envió con otro usuario «clon» en las últimas horas',true));
			}
		}
	}
	
	function checkLinksSentByUser(){
		// Check the number of links sent by a user
		if($limit_user_24_hours=Configure::read('Monky.Links.limit_user_24_hours')>0){
			$queued_24_hours = (int) $this->Link->find('count',array('conditions'=>array('NOT'=>array('Link.status'=>'published'),'Link.created > date_sub(now(), interval 24 hour)','Link.user_id'=>$this->id),'recursive'=>-1));

			if ($queued_24_hours > $limit_user_24_hours) {
				throw new AddLinkException(__('debes esperar, tienes demasiados envíos en cola de las últimas 24 horas',true));
			}
		}
	}
	
	function checkLinksSentByUserInLast3Minutes(){
		
		if($this->field('karma') > Configure::read('Monky.Links.limit_3_minutes_karma')){
			$enqueued_limit = Configure::read('Monky.Links.limit_3_minutes') * 1.5;
		}else{
	 		$enqueued_limit = Configure::read('Monky.Links.limit_3_minutes');
		}
		
		$enqueued_last_minutes = (int) $this->Link->find('count',array('conditions'=>array('Link.status'=>'queued','Link.created > date_sub(now(), interval 3 minute)','Link.user_id'=>$this->id),'recursive'=>-1));
		
		if ($enqueued_last_minutes > $enqueued_limit) {
			throw new AddLinkException(__('se han enviado demasiadas historias en los últimos 3 minutos',true));
		}
	}
	
	function checkUserHaveEnoughVotes(){
		// check that a new user also votes, not only sends links
		// it requires $globals['min_user_votes'] votes
		if ($this->isNewUSer() && Configure::read('Monky.User.min_votes') > 0 && $this->field('karma') < Configure::read('Monky.User.new_user_karma')) {
			$user_links = 1 + $this->Link->find('count',array('conditions'=>array('user_id'=>$this->id, 'Link.created > date_sub(now(), interval 24 hour)',	'NOT'=>array('Link.status'=> 'discard')),'recursive'=>-1));

			$min_votes = Configure::read('Monky.User.min_votes');
			if ($user_links > 1) {
				$total_links = $this->Link->find('count',array('conditions'=>array('Link.created > date_sub(now(), interval 24 hour)','Link.status'=> 'queued'),'recursive'=>-1));
				$min_votes = min(4, intval($total_links/20)) * $user_links;
			}
			
			$user_votes = $this->Vote->find('count',array('conditions'=>array('type'=>'links','user_id'=>$this->id,'Vote.created > date_sub(now(), interval 72 hour)'),'recursive'=>-1));
			
			$needed = $min_votes - $user_votes;
								
			throw new AddLinkException(
				sprintf(__('you need at least %s votes to be able to add links',true),$needed).
				sprintf(__('take your time to vote, if you vote quickly your karma will decrease. <a href="%s">click here to start voting</a>',true),Router::url(array('controller'=>'links','action'=>'shakeit')))
			);
		}
	}

	function checkRubbishAndSpamSending(){
		// avoid spams, an extra security check
		// it counts the numbers of links in the last hours
		if ($this->isNewUSer()) {
			$user_links_limit = Configure::read('Monky.Links.new_user_limit');
			$user_links_interval = intval(Configure::read('Monky.Links.new_user_interval') / 3600);
		} else {
			$user_links_limit =Configure::read('Monky.Links.user_limit'); 
			$user_links_interval = intval(Configure::read('Monky.Links.user_interval') / 3600);
		}
		
		$same_user = $this->Link->find('count',array('conditions'=>array('Link.created > date_sub(now(), interval '.$user_links_interval.' hour)','Link.user_id'=>$this->id),'recursive'=>-1));
		$same_ip = $this->Link->find('count',array('conditions'=>array('Link.created > date_sub(now(), interval '.$user_links_interval.' hour)','Link.ip'=>Visitor::ip()),'recursive'=>-1));
		
		if ($same_user >  $user_links_limit  || $same_ip >  $user_links_limit  ) {
			throw new AddLinkException(__('debes esperar, ya se enviaron varias con el mismo usuario o dirección IP',true));
		}
	
		// avoid users sending continuous "rubbish" or "propaganda", specially new users
		// it takes in account the number of positive votes in the last six hours
		if ($same_user > 1 && $this->field('karma') < Configure::read('Monky.Karma.propaganda')) {
			$positives_received = $this->Link->field('sum(votes)',array('Link.created > date_sub(now(), interval '.$user_links_interval.' hour)', 'Link.user_id'=>$user->id));
			//db->get_var("select sum(link_votes) from links where link_date > date_sub(now(), interval $user_links_interval hour) and link_author = $current_user->user_id");
			$negatives_received = $this->Link->field('sum(negatives)',array('Link.created > date_sub(now(), interval '.$user_links_interval.' hour)', 'Link.user_id'=>$user->id));
			
			if ($negatives_received > 10 && $negatives_received > $positives_received * 1.5) {
				throw new AddLinkException(__('debes esperar, has tenido demasiados votos negativos en tus últimos envíos',true));
			}
		}
	}
	
	function getAffinity($id, $from = false) {
		//@todo
		return false;
	}
	
	function isNewUSer(){
		$user_created=getUnixtime($this->field('created'));

		if ((time() - $user_created < Configure::read('Monky.User.new_user_time') ) || (!$this->getSentLinks()==0)) {
			return true;
		}
		
		return false;
	}
	
	function getSentLinks($days=null){
		$conditions=array('Link.user_id'=>$this->id);
		if($days) $conditions[]='Link.created > date_sub(now(), interval '.$days.' day)';
		
		return $this->Link->find('count',array('conditions'=>$conditions,'recursive'=>-1));
	}

	function cantPostComment($user_id){
		//@todo
		return false;
	}
}

class AddLinkException extends Exception{};
class UserErrorException extends Exception{};

?>